package com.bbf.tio.common;

import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.core.exception.AioDecodeException;
import org.tio.server.intf.ServerAioHandler;

import java.nio.ByteBuffer;

public abstract class TioAbstractHandler implements ServerAioHandler<Object, TioPacket, Object> {
  /**
   * 编码：把业务消息包编码为可以发送的ByteBuffer
   * 总的消息结构：消息头 + 消息体
   * 消息头结构：    4个字节，存储消息体的长度
   * 消息体结构：   对象的json串的byte[]
   */
  @Override
  public ByteBuffer encode(TioPacket packet, GroupContext<Object, TioPacket, Object> groupContext,
                           ChannelContext<Object, TioPacket, Object> channelContext) {
    System.out.println(packet.toString());
    byte[] body = packet.getBody();
    int bodyLen = 0;
    if (body != null) {
      bodyLen = body.length;
    }
    //bytebuffer的总长度是 = 消息头的长度 + 消息体的长度
    int allLen = TioConstants.HEADER_LENGHT + bodyLen;
    //创建一个新的bytebuffer
    ByteBuffer buffer = ByteBuffer.allocate(allLen);
    //设置字节序
    buffer.order(groupContext.getByteOrder());
    //写入消息头----消息头的内容就是消息体的长度
    buffer.putInt(allLen);
    //写入消息体
    if (body != null) {
      buffer.put(body);
    }
    return buffer;
  }

  /**
   * 解码：把接收到的ByteBuffer，解码成应用可以识别的业务消息包
   * 总的消息结构：消息头 + 消息体
   * 消息头结构：    4个字节，存储消息体的长度
   * 消息体结构：   对象的json串的byte[]
   */
  @Override
  public TioPacket decode(ByteBuffer buffer, ChannelContext<Object, TioPacket, Object> channelContext) throws AioDecodeException {
    int readableLength = buffer.limit() - buffer.position();
    //为兼容其他socket发送，接收端不要实现 head 4字节，可以参考test/TioClientHandler.java -> decode
//    //收到的数据组不了业务包，则返回null以告诉框架数据不够
//    if (readableLength < TioConstants.HEADER_LENGHT) {
//      return null;
//    }
//    //读取消息体的长度
//    int bodyLength = buffer.getInt();
//    //数据不正确，则抛出AioDecodeException异常
//    if (bodyLength < 0) {
//      throw new AioDecodeException("bodyLength [" + bodyLength + "] is not right, remote:" +
//          channelContext.getClientNode());
//    }
//    //收到的数据是否足够组包
//    int isDataEnough = readableLength - TioConstants.HEADER_LENGHT;
    int isDataEnough = readableLength;
    // 不够消息体长度(剩下的buffe组不了消息体)
    if (isDataEnough < 0) {
      return null;
    } else {
      //组包成功
      TioPacket imPacket = new TioPacket();
      if (isDataEnough > 0) {
        byte[] dst = new byte[isDataEnough];
        buffer.get(dst);
        imPacket.setBody(dst);
      }
      return imPacket;
    }
  }
}
